<template>
    <div class="proTable-container" >
        <div class="search-part" ref="searchPartRef" :class="{ 'show-search': !showSearchFlag }" v-if="!hideSearch">
            <el-card class="search-card">
                <div class="searchForm-container">
                    <div class="search-form">
                        <el-form :label-width="tableOptions.labelWidth" label-position="right" ref="formRef">
                            <el-row :gutter="15">
                                <template v-for="item in tableOptions.columns" :key="item.prop">
                                    <el-col ref="colRef" :span="item.search?.el !== 'date' ? 8 : 16" v-if="item.search && item.isSearch ">
                                        <el-form-item :label="item.label" v-if="!item.searchSlot">
                                            <el-input v-if="item.search?.el == 'input'" v-model="search[item.prop]"
                                                :placeholder="`请输入${item.label}`" clearable></el-input>
                                            <el-select v-if="item.search?.el == 'select'" v-model="search[item.prop]"
                                                :placeholder="`请选择${item.label}`" clearable>
                                                <el-option v-for="select in item.search.options.data" :key="select.value"
                                                    :label="select.label" :value="select.value"></el-option>
                                            </el-select>
                                            <el-date-picker v-if="item.search?.el == 'date'" v-model="search[item.prop]"
                                                :type="item.search.options.type" range-separator="-"
                                                start-placeholder="开始时间" end-placeholder="结束时间" clearable></el-date-picker>
                                        </el-form-item>
                                    </el-col>
                                    <el-col ref="colRef" :span="8" v-if="!item.search && item.searchSlot && item.isSearch">
                                        <slot :name="`${item.prop}Search`"></slot>
                                    </el-col>
                                </template>
                                <slot name="searchExpand"></slot>
                            </el-row>
                        </el-form>
                    </div>

                    <div class="search-btn">
                        <el-button type="primary" @click="handleSearch">搜索</el-button>
                        <el-button @click="handleInit">重置</el-button>
                        <el-button type="primary" link @click="handleExpand" style="height: 32px" v-if="showExpandIcon">
                            {{ collapsed ? "展开" : "合并" }}
                            <el-icon class="el-icon--right">
                                <component :is="collapsed ? ArrowDown : ArrowUp"></component>
                            </el-icon>
                        </el-button>
                    </div>
                </div>
            </el-card>
        </div>

        <div class="table-part">
            <el-card>
                <div class="table-container">
                    <div class="table-header">
                        <div class="header-left">
                            <slot name="tableBtn"></slot>
                        </div>
                        <div class="header-right" v-if="showTool">
                            <slot name="toolButton">
                                <el-button :icon="Refresh" circle @click="handleRefresh"/>
                                <el-button :icon="Printer" circle v-if="tableOptions.columns.length" />
                                <el-button :icon="Operation" circle v-if="tableOptions.columns.length"
                                    @click="handleSetCol" />
                                <el-button :icon="Search" circle v-if="searchColumns" @click="showSearchPart" />
                            </slot>
                        </div>
                    </div>

                    <el-table :border="border" :row-key="rowKey" :data="data" :stripe="stripe" highlight-current-row
                        @current-change="handleRowClick" @selection-change="handleSelect" v-loading="loading"
                        :style="{ height: showPage ? 'calc(100% - 120px)' : 'calc(100% - 80px)' }">
                        <el-table-column type="selection" width="55" align="center"
                            v-if="tableOptions.selection"></el-table-column>
                        <el-table-column type="expand" v-slot="scope" fixed="left" v-if="tableOptions.expand">
                            <slot name="expand" v-bind="scope"></slot>
                        </el-table-column>
                        <el-table-column width="55" align="center" v-if="tableOptions.index" label="序号" fixed="left">
                            <template #default="{ $index }">
                                {{ ((page.pageNumber - 1)*page.pageSize) + $index + 1 }}
                            </template>
                        </el-table-column>

                        <template v-for="(item, index) in tableOptions.columns" :key="item.prop">
                            <el-table-column :label="item.label" v-if="item.isShow" :fixed="item.flex" :width="item.width"
                                :align="item.align ?? 'center'" :prop="item.prop" :sortable="item.sort">
                                <template v-if="item.slot" #default="{ row, $index }">
                                    <slot :row="row" :$index="$index" :name="`${item.prop}`" />
                                </template>
                            </el-table-column>
                        </template>

                        <!-- 无数据 -->
                        <template #empty>
                            <div class="table-empty">
                                <slot name="empty">
                                    <img src="@/assets/images/notData.png" alt="notData" />
                                    <div>暂无数据</div>
                                </slot>
                            </div>
                        </template>
                    </el-table>

                    <el-pagination v-if="showPage" v-model:current-page="page.pageNumber" v-model:page-size="page.pageSize"
                        :page-sizes="page.pageSizes" layout="total, sizes, prev, pager, next, jumper" :total="page.total"
                        @size-change="handleSizeChange" @current-change="handleCurrentChange" />
                </div>
            </el-card>
        </div>
        <ColSetting ref="colSettingRef" v-model:colSetting="tableOptions.columns" @init-search="handleInitExpand"/>
    </div>
</template>

<script setup lang="ts">
import { ELComponentInstance } from "@/type/components/element-plus";
import { Page, ProTableType, ColSettingType } from "@/type/proTable";
import {
    ArrowDown,
    ArrowUp,
    Refresh,
    Printer,
    Operation,
    Search,
} from "@element-plus/icons-vue";
import ColSetting from "./components/colSetting.vue";

const emits = defineEmits([
    "search",
    "init",
    "rowClick",
    "select",
    "changePageNUmber",
    "changePageSize",
    "refresh",
]);

interface ProTableProps {
    tableOptions: ProTableType; //配置项
    search?: any; //查询条件
    data: any; //表格数据
    border?: boolean;//表格边框
    rowKey?: string;//rowkey
    showTool?: boolean; //头部右侧功能按键
    stripe?: boolean; //表格斑马条纹
    page?: Page;//分页组件
    showPage?: boolean;//是否展示分页
    hideSearch?: boolean;//是否隐藏查询部分
    loading?: boolean;//表格加载
}

//接收props参数并设置默认值
const props = withDefaults(defineProps<ProTableProps>(), {
    tableOptions: () => {
        return {} as ProTableType;
    },
    search: {},
    data: [],
    border: true,
    rowKey: "id",
    showTool: true,
    stripe: true,
    page: () => {
        return {
            pageSize: 50,
            pageNumber: 1,
            total: 0,
            pageSizes: [20, 50, 100]
        } as Page;
    },
    showPage: true,
    hideSearch: false,
    loading: false
});

// 接收 tableOptions 并设置为响应式
const { tableOptions } = toRefs(props)

//设置列配置默认值
const setDefaultOptions = () => {
    tableOptions.value.columns = tableOptions.value.columns.map(item => ({ ...item, isShow: item.isShow ?? true, sort: item.sort ?? false,isSearch:item.isSearch??true }))
}

const searchPartRef = ref<HTMLDivElement>();

const handleRefresh = () => {
    emits("refresh")
}

const handleSearch = () => {
    emits("search");
};

const handleInit = () => {
    emits("init");
};

const handleRowClick = (val: any) => {
    emits("rowClick", val);
};

const handleSelect = (val: any) => {
    emits("select", val);
};

const handleSizeChange = (val: number) => {
    emits("changePageSize", val);
};

const handleCurrentChange = (val: number) => {
    emits("changePageNUmber", val);
};

const formRef = ref<ELComponentInstance["formRef"]>();

const colRef = ref<ELComponentInstance["colRef"]>();

const collapsed = ref(true);

const searchColumns = ref(0);

const showExpandIcon = ref(true);

onMounted(() => {
    setDefaultOptions()
    !props.hideSearch && handleInitExpand();
});

// 展开合并
const handleExpand = () => {
    if (collapsed.value == false) {
        collapsed.value = true;
        handleInitExpand();
    } else {
        collapsed.value = false;
        Array(colRef.value).flat().forEach(
            (item: any, index: number) => {
                (
                    document.querySelector(".search-form")?.querySelectorAll(".el-col")[
                    index
                    ] as HTMLElement
                ).style.display = "block";
            }
        );
    }
};

// 初始化表单
const handleInitExpand = () => {
    nextTick(() => {
        let sum = 0;
        searchColumns.value = Array(colRef.value).flat().length
        Array(colRef.value).flat().forEach(
            (item: any, index: number) => {
                sum = item.span + sum;
                const dom = document.querySelector(".search-form")?.querySelectorAll(".el-col")[index] as HTMLElement
                dom.style.display = "block";
                if (sum > 24) {
                    dom.style.display = "none";
                }
            }
        );
        showExpandIcon.value = sum <= 24?false:true;
    })
};

const showSearchFlag = ref(true);
const showSearchPart = () => {
    if (showSearchFlag.value) {
        showSearchFlag.value = false;
    } else {
        showSearchFlag.value = true;
    }
};

const colSettingRef = ref<ColSettingType>()
const handleSetCol = () => {
    colSettingRef.value?.handleShow()
}
</script>

<style lang="scss">
.proTable-container {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;

    .search-part {
        margin-bottom: 12px;

        .search-card {
            padding: 18px 18px 0;

            .searchForm-container {
                display: flex;
                justify-content: space-between;

                .search-form {
                    width: 80%;

                    .el-select {
                        width: 100%;

                        .el-input__wrapper {
                            width: 100%;
                        }
                    }

                    .el-input {
                        width: 100%;
                    }

                    .el-input-number {
                        width: 100%;
                    }
                }

                .search-btn {
                    width: 20%;
                    height: 50px;
                    display: flex;
                    justify-content: end;
                }
            }

            .el-card__body {
                padding: 0;
            }
        }
    }

    .show-search {
        display: none;
    }

    .table-part {
        position: relative;
        flex: 1;

        .el-card {
            height: 100%;

            .el-card__body {
                height: 100%;

                .table-container {
                    height: 100%;

                    .table-header {
                        display: flex;
                        justify-content: space-between;
                        margin-bottom: 12px;
                    }

                    .el-table {
                        height: 80%;
                    }

                    .el-pagination {
                        height: 40px;
                        display: flex;
                        justify-content: end;
                        margin-top: 4px;
                    }
                }
            }
        }
    }
}
</style>
